package com.mzj.saas.mservice.my.service;

import com.alibaba.fastjson.JSON;
import com.alipay.api.response.AlipayFundTransToaccountTransferResponse;
import com.mzj.saas.commons.*;
import com.mzj.saas.commons.enums.OSSUploadFileTypeEnum;
import com.mzj.saas.commons.enums.PaymentTypeEnum;
import com.mzj.saas.commons.enums.UserLoginTypeEnum;
import com.mzj.saas.commons.util.DateUtils;
import com.mzj.saas.commons.vo.redis.TokenRedisVo;
import com.mzj.saas.config.oss.OssConfig;
import com.mzj.saas.config.pay.PayConfig;
import com.mzj.saas.mservice.area.entity.Area;
import com.mzj.saas.mservice.area.repository.AreaRepository;
import com.mzj.saas.mservice.community.entity.Community;
import com.mzj.saas.mservice.community.entity.CommunityBuild;
import com.mzj.saas.mservice.community.entity.CommunityBuildUnit;
import com.mzj.saas.mservice.community.repository.CommunityBuildRepository;
import com.mzj.saas.mservice.community.repository.CommunityBuildUnitRepository;
import com.mzj.saas.mservice.community.repository.CommunityRepository;
import com.mzj.saas.mservice.department.entity.UserDepartmentRef;
import com.mzj.saas.mservice.department.repository.UserDepartmentRefRepository;
import com.mzj.saas.mservice.eligible.entity.DepartmentEnterpriseTagRef;
import com.mzj.saas.mservice.eligible.entity.DepartmentHierarchy;
import com.mzj.saas.mservice.eligible.repository.DepartmentEnterpriseTagRefRepository;
import com.mzj.saas.mservice.eligible.repository.DepartmentHierarchyRepository;
import com.mzj.saas.mservice.house.entity.HouseMatchUser;
import com.mzj.saas.mservice.house.repository.HouseMatchUserRepository;
import com.mzj.saas.mservice.idcard.service.IdcardService;
import com.mzj.saas.mservice.idcard.vo.IdcardVO;
import com.mzj.saas.mservice.lock.Repository.SmartLockAuthRepository;
import com.mzj.saas.mservice.lock.entity.SmartLockAuth;
import com.mzj.saas.mservice.my.entity.HouseBind;
import com.mzj.saas.mservice.my.repository.HouseBindRepository;
import com.mzj.saas.mservice.my.vo.*;
import com.mzj.saas.mservice.oss.service.OSSService;
import com.mzj.saas.mservice.property.entity.CommunityHouseUser;
import com.mzj.saas.mservice.property.repository.CommunityHouseUserRepository;
import com.mzj.saas.mservice.sys.entity.AppUser;
import com.mzj.saas.mservice.sys.entity.User;
import com.mzj.saas.mservice.sys.entity.WechatAccount;
import com.mzj.saas.mservice.sys.entity.WithdrawUser;
import com.mzj.saas.mservice.sys.repository.AppUserRepository;
import com.mzj.saas.mservice.sys.repository.UserRepository;
import com.mzj.saas.mservice.sys.repository.WechatAccountRepository;
import com.mzj.saas.mservice.sys.repository.WithdrawUserRepository;
import com.mzj.saas.mservice.sys.service.UserService;
import com.mzj.saas.mservice.token.service.TokenService;
import com.mzj.saas.mservice.wallet.entity.Wallet;
import com.mzj.saas.mservice.wallet.entity.WithdrawRecord;
import com.mzj.saas.mservice.wallet.entity.WithdrawTransferRecord;
import com.mzj.saas.mservice.wallet.repository.WalletRepository;
import com.mzj.saas.mservice.wallet.repository.WithdrawRecordRepository;
import com.mzj.saas.mservice.wallet.repository.WithdrawTransferRecordRepository;
import com.mzj.saas.mservice.wallet.vo.WalletDetailVO;
import com.mzj.saas.mservice.wallet.vo.WalletVO;
import com.mzj.saas.mservice.wallet.vo.WithdrawRecordVO;
import com.mzj.saas.redis.RedisService;
import com.mzj.saas.sdk.withdraw.ali.AliTransfers;
import com.mzj.saas.sdk.withdraw.vo.AliWithdraw;
import com.mzj.saas.sdk.withdraw.vo.WxWithdraw;
import com.mzj.saas.sdk.withdraw.vo.WxWithdrawRes;
import com.mzj.saas.sdk.withdraw.wx.WxTransfersRequest;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static com.mzj.saas.mservice.sys.service.LoginService.HASH_INTERATIONS;

@Service
public class MyService {
    private static final Logger log = LoggerFactory.getLogger(MyService.class);

    private static final String ORDER = " ORDER BY h.create_time DESC";
    private static final String SQL_PAGE = " LIMIT ? OFFSET ?";

    @Autowired
    private PayConfig payConfig;
    @Autowired
    private RedisService redisService;
    @Autowired
    private AppUserRepository appUserRepository;
    @Autowired
    private DepartmentHierarchyRepository departmentHierarchyRepository;
    @Autowired
    private DepartmentEnterpriseTagRefRepository departmentEnterpriseTagRefRepository;
    @Autowired
    private HouseMatchUserRepository houseMatchUserRepository;
    @Autowired
    private CommunityHouseUserRepository communityHouseUserRepository;
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private HouseBindRepository houseBindRepository;
    @Autowired
    private OSSService ossService;
    @Autowired
    private OssConfig ossConfig;
    @Autowired
    private IdcardService idcardService;
    @Autowired
    @Qualifier("stringRedisTemplate")
    private StringRedisTemplate redisTemplate;
    @Autowired
    private AreaRepository areaRepository;
    @Autowired
    private CommunityRepository communityRepository;
    @Autowired
    private CommunityBuildRepository communityBuildRepository;
    @Autowired
    private CommunityBuildUnitRepository communityBuildUnitRepository;
    @Autowired
    private WechatAccountRepository wechatAccountRepository;
    @Autowired
    private WithdrawRecordRepository withdrawRecordRepository;
    @Autowired
    private WithdrawTransferRecordRepository withdrawTransferRecordRepository;
    @Autowired
    private WalletRepository walletRepository;
    @Autowired
    private WithdrawUserRepository withdrawUserRepository;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private UserService userService;
    @Autowired
    private UserDepartmentRefRepository userDepartmentRefRepository;
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private SmartLockAuthRepository smartLockAuthRepository;
    /**
     *  我的信息
     * @param accessToken
     * @return
     */
    public ResultBean<MyInfoVO> findMyInfo(String accessToken) {
        try {
            TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
            if (tokenRedisVo == null) {
                return ResultBean.failedResultOfToken();
            }
            Integer loginType = 1;
            String userId = tokenRedisVo.getId();
            Long enterpriseId = tokenRedisVo.getEnterpriseId();

            User user = userRepository.findByMobile(tokenRedisVo.getPhone());
            String userName = user.getName();
            if (user == null) {
                return ResultBean.failedResultWithMsg("用户不存在");
            }

            String phone = user.getMobile();


            // 用户类型
            List<String> userType = new ArrayList<>();
            DepartmentHierarchy hierarchy = departmentHierarchyRepository.findByOrgIdAndStatus(enterpriseId, 1);
            if (hierarchy == null) {
                return ResultBean.failedResultWithMsg("用户所属机构未设置层级架构");
            }
            Long id = hierarchy.getId();
            List<DepartmentEnterpriseTagRef> refs = departmentEnterpriseTagRefRepository.findByDepRefId(id);
            List<Long> enterpriseTagIds = refs.stream().map(DepartmentEnterpriseTagRef::getTagId).distinct()
                    .collect(Collectors.toList());// 用户企业标签
            if (!enterpriseTagIds.isEmpty()) {
                for (Long enterpriseTagId : enterpriseTagIds) {
                    if (enterpriseTagId == 2L) {
                        String str = "产权单位";
                        userType.add(str);
                    } else if (enterpriseTagId == 4L) {
                        String str = "物业";
                        userType.add(str);
                    }
                }
            }

            // 房屋绑定状态
            List<HouseBind> houseBinds = houseBindRepository.findByUserIdAndStatus(userId, 1);
            Integer houseBindStatus;
            if (houseBinds.isEmpty()) {
                houseBindStatus = 0;
            } else {
                houseBindStatus = 1;
            }


            MyInfoVO vo = new MyInfoVO();
            vo.setUserId(userId);
            vo.setUserName(userName);
            vo.setUserType(userType);
            vo.setPhone(phone);
            vo.setHouseBindStatus(houseBindStatus);
            vo.setLoginType(loginType);
            vo.setType(1);

            return ResultBean.successfulResult(vo);
        } catch (Exception e) {
            log.error("MyService findMyInfo Exception = {}" + e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }

    public ResultBean<Object> uploadIdCard(String accessToken, Integer type, MultipartFile file) {
        try {
            if (type == null) {
                return ResultBean.failedResultOfParamWithMsg("照片类型为空");
            }
            if (file == null) {
                return ResultBean.failedResultOfParamWithMsg("上传照片为空");
            }

            /*String str = "";
            if (type == 1) {
                str = "frontCard:fileKey:";
            } else if (type == 2) {
                str = "backCard:fileKey:";
            }*/

            /*// 如果有缓存，先删除上传文件
            Object object = redisTemplate.opsForValue().get(str + cardNumber);
            if (object != null) {
                String fileKey = object.toString();
                ossService.deleteObject(ossConfig.getOssBucketName(), fileKey);
            }*/

            ResultBean<Object> objectResultBean = ossService.putFile(ossConfig.getOssBucketName(), file,
                    OSSUploadFileTypeEnum.PROVE.toString());
            String code = objectResultBean.getCode();
            String msg = objectResultBean.getMsg();
            if (!code.equals(StatusCode.SUCCESS_CODE_10000.getErrorCode())) {
                return ResultBean.failedResultWithCodeAndMsg(code, msg);
            } else {
                String fileKey = objectResultBean.getResultData().toString();
                //redisTemplate.opsForValue().set(str + cardNumber, fileKey, 5, TimeUnit.MINUTES);
                String url = ossService.getOssFilePath(fileKey);

                Map<Object, Object> map = new HashMap<>();
                if (type == 1) {
                    // 校验身份证正面
                    ResultBean<IdcardVO> faceResultBean = idcardService.idcardToAppCode(accessToken, url,
                            "face", null, null);
                    log.info(" certification, result={}", JSON.toJSONString(faceResultBean.getResultData()));
                    String backCode = faceResultBean.getCode();
                    if (!backCode.equals(StatusCode.SUCCESS_CODE_10000.getErrorCode())) {
                        return ResultBean.failedResultWithMsg("身份证正面信息验证有误");
                    } else {
                        IdcardVO idcardVO = faceResultBean.getResultData();
                        if (StringUtils.isEmpty(idcardVO.getName()) || StringUtils.isEmpty(idcardVO.getNum())) {
                            return ResultBean.failedResultWithMsg("身份证正面信息验证有误");
                        }

                        map.put("name", idcardVO.getName());
                        map.put("cardNumber", idcardVO.getNum());
                        map.put("url", url);
                    }
                }

                if (type == 2) {
                    // 校验身份证背面
                    ResultBean<IdcardVO> backResultBean = idcardService.idcardToAppCode(accessToken, url,
                            "back", null, null);
                    log.info(" certification, result={}", JSON.toJSONString(backResultBean.getResultData()));
                    String backCode = backResultBean.getCode();
                    if (!backCode.equals(StatusCode.SUCCESS_CODE_10000.getErrorCode())) {
                        return ResultBean.failedResultWithMsg("身份证背面信息验证有误");
                    } else {
                        IdcardVO idcardVO = backResultBean.getResultData();
                        if (StringUtils.isEmpty(idcardVO.getIssue()) || StringUtils.isEmpty(idcardVO.getStart_date())) {
                            return ResultBean.failedResultWithMsg("身份证背面信息验证有误");
                        }

                        map.put("url", url);
                    }
                }

                return ResultBean.successfulResult(map);
            }
        } catch (Exception e) {
            log.error("MyService uploadIdCard Exception = {}" + e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }

    /*public ResultBean<Object> certification(String accessToken, CertificationVO vo) {
        try {
            TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
            if (tokenRedisVo == null) {
                return ResultBean.failedResultOfToken();
            }
            String userId = tokenRedisVo.getId();

            if (StringUtils.isBlank(vo.getName())) {
                return ResultBean.failedResultOfParamWithMsg("姓名不存在");
            }
            if (StringUtils.isBlank(vo.getPhone())) {
                return ResultBean.failedResultOfParamWithMsg("手机号不存在");
            }
            if (StringUtils.isBlank(vo.getCardNumber())) {
                return ResultBean.failedResultOfParamWithMsg("身份证号码不存在");
            }
            if (StringUtils.isBlank(vo.getFrontCardNumberPic())) {
                return ResultBean.failedResultOfParamWithMsg("身份证人像面不存在");
            }
            if (StringUtils.isBlank(vo.getBackCardNumberPic())) {
                return ResultBean.failedResultOfParamWithMsg("身份证国徽面不存在");
            }
            if (StringUtils.isBlank(vo.getCode())) {
                return ResultBean.failedResultOfParamWithMsg("验证码为空");
            }

            String phone = vo.getPhone();
            String phoneCode = vo.getCode();
            if (StringUtils.isNotBlank(phone) && StringUtils.isNotBlank(phoneCode)) {
                // 验证验证码
                String redisPhone = redisService.getSmsCodeMobile(phoneCode);
                if (!StringUtils.isBlank(redisPhone)) {
                    if (redisPhone.equals(phone)) {

                        // 校验名字、身份证号码与身份证信息是否一致
                        ResultBean<IdcardVO> resultBean = idcardService.idcardToAppCode(accessToken, vo.getFrontCardNumberPic(),
                                "face", null, null);
                        String code = resultBean.getCode();
                        String msg = resultBean.getMsg();
                        if (!code.equals(StatusCode.SUCCESS_CODE_10000.getErrorCode())) {
                            return ResultBean.failedResultWithCodeAndMsg(code, msg);
                        } else {
                            IdcardVO idcardVO = resultBean.getResultData();
                            if (!idcardVO.getName().equals(vo.getName())) {
                                return ResultBean.failedResultWithMsg("输入的姓名与上传身份证照片的姓名不一致");
                            }
                            if (!idcardVO.getNum().equals(vo.getCardNumber())) {
                                return ResultBean.failedResultWithMsg("输入的身份证号码与上传身份证照片的号码不一致");
                            }
                        }

                        // 校验身份证背面
                        ResultBean<IdcardVO> backResultBean = idcardService.idcardToAppCode(accessToken, vo.getBackCardNumberPic(),
                                "back", null, null);
                        log.info(" certification, result={}", JSON.toJSONString(backResultBean.getResultData()));
                        String backCode = backResultBean.getCode();
                        if (!backCode.equals(StatusCode.SUCCESS_CODE_10000.getErrorCode())) {
                            return ResultBean.failedResultWithMsg("身份证背面信息验证有误");
                        } else {
                            IdcardVO idcardVO = backResultBean.getResultData();
                            if (StringUtils.isEmpty(idcardVO.getIssue()) || StringUtils.isEmpty(idcardVO.getStart_date())) {
                                return ResultBean.failedResultWithMsg("身份证背面信息验证有误");
                            }
                        }

                        // 查身份证号码是否已认证
                        AppUser existUser = appUserRepository.findByCardNumber(vo.getCardNumber());
                        if (existUser != null) {
                            return ResultBean.failedResultWithMsg("该身份证已实名认证");
                        }

                        AppUser user = appUserRepository.findByIdOrEnterpriseUserId(userId, userId);
                        if (!user.getPhone().equals(vo.getPhone())) {
                            return ResultBean.failedResultWithMsg("请使用登录手机号码进行认证");
                        }

                        user.setName(vo.getName());
                        user.setCardNumber(vo.getCardNumber());
                        user.setFrontCardNumberPic(vo.getFrontCardNumberPic());
                        user.setBackCardNumberPic(vo.getBackCardNumberPic());
                        user.setCertificationStatus(1);
                        appUserRepository.save(user);

                    } else {
                        return ResultBean.failedResultWithMsg("验证码已失效");
                    }
                } else {
                    return ResultBean.failedResultWithMsg("验证码未找到或已过期");
                }
            }

            return ResultBean.successfulResult(null);
        } catch (Exception e) {
            log.error("MyService certification Exception = {}" + e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }*/

    /**
     * 实名认证
     * @param accessToken
     * @param vo
     * @return
     */
    public ResultBean<Object> certification(String accessToken, CertificationVO vo) {
        try {
            TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
            if (tokenRedisVo == null) {
                return ResultBean.failedResultOfToken();
            }
            String userId = tokenRedisVo.getId();

            if (StringUtils.isBlank(vo.getName())) {
                return ResultBean.failedResultOfParamWithMsg("姓名不存在");
            }
            if (StringUtils.isBlank(vo.getPhone())) {
                return ResultBean.failedResultOfParamWithMsg("手机号不存在");
            }
            if (StringUtils.isBlank(vo.getCardNumber())) {
                return ResultBean.failedResultOfParamWithMsg("身份证号码不存在");
            }
            if (StringUtils.isBlank(vo.getFrontCardNumberPic())) {
                return ResultBean.failedResultOfParamWithMsg("身份证人像面不存在");
            }
            if (StringUtils.isBlank(vo.getBackCardNumberPic())) {
                return ResultBean.failedResultOfParamWithMsg("身份证国徽面不存在");
            }
            if (StringUtils.isBlank(vo.getCode())) {
                return ResultBean.failedResultOfParamWithMsg("验证码为空");
            }

            String phone = vo.getPhone();
            String phoneCode = vo.getCode();
            if (StringUtils.isNotBlank(phone) && StringUtils.isNotBlank(phoneCode)) {
                // 验证验证码
                String redisPhone = redisService.getSmsCodeMobile(phoneCode);
                if (!StringUtils.isBlank(redisPhone)) {
                    if (redisPhone.equals(phone)) {
                        // 查身份证号码是否已认证
                        AppUser existUser = appUserRepository.findByCardNumber(vo.getCardNumber());
                        if (existUser != null) {
                            return ResultBean.failedResultWithMsg("该身份证已实名认证");
                        }

                        User orgUser = userRepository.findByMobile(phone);
                        if (orgUser != null) {
                            if (!orgUser.getName().equals(vo.getName())) {
                                return ResultBean.failedResultWithMsg("真实姓名与企业账号姓名不符");
                            }
                        }

                        AppUser user = appUserRepository.findByIdOrEnterpriseUserId(userId, userId);
                        user.setName(vo.getName());
                        user.setCardNumber(vo.getCardNumber());
                        user.setFrontCardNumberPic(vo.getFrontCardNumberPic());
                        user.setBackCardNumberPic(vo.getBackCardNumberPic());
                        user.setCertificationStatus(1);
                        user.setFacePic(vo.getFacePic());
                        appUserRepository.save(user);
                    } else {
                        return ResultBean.failedResultWithMsg("验证码不正确");
                    }
                } else {
                    return ResultBean.failedResultWithMsg("验证码未找到或已过期");
                }
            }

            return ResultBean.successfulResult(null);
        } catch (Exception e) {
            log.error("MyService certification Exception = {}" + e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }

    @Transactional
    public ResultBean<Object> houseBind(String accessToken, String phone, String code, String cardNumber) {
        try {
            TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
            if (tokenRedisVo == null) {
                return ResultBean.failedResultOfToken();
            }
            String userId = tokenRedisVo.getId();
            Long enterpriseId = tokenRedisVo.getEnterpriseId();

            Date date = new Date();
            List<HouseBindVO> list = new ArrayList<>();
            List<Object> args = new ArrayList<>();

            if (StringUtils.isNotBlank(phone) && StringUtils.isNotBlank(code)) {
                // 验证验证码
                String redisPhone = redisService.getSmsCodeMobile(code);
                if (!StringUtils.isBlank(redisPhone)) {
                    if (redisPhone.equals(phone)) {
                        // 手机号码查房屋
                        if (StringUtils.isNotBlank(phone)) {
                            args.add(phone);
                            args.add(phone);
                            args.add(phone);
                            args.add(enterpriseId);
                            String sql = "SELECT u.`house_id` AS houseId,1 AS TYPE,1 AS ownerType\n" +
                                    "FROM `saas_house_eligible_apply` a JOIN `saas_house_match_user` u ON a.id = u.`apply_id`\n" +
                                    "WHERE u.`status` = 1 AND a.`mobile` = ?\n" +
                                    "UNION\n" +
                                    "SELECT u.`house_id` AS houseId,1 AS TYPE,2 AS ownerType\n" +
                                    "FROM `saas_house_eligible_apply_cohabit` c JOIN `saas_house_match_user` u ON c.apply_id = u.`apply_id`\n" +
                                    "WHERE u.`status` = 1 and c.status in (1,4) AND c.`mobile` = ?\n" +
                                    "UNION\n" +
                                    "SELECT hu.community_house_id AS houseId,2 AS TYPE,(CASE hu.type WHEN 1 THEN 3 WHEN 2 THEN 4 END) AS ownerType\n" +
                                    "FROM saas_community_house_user hu WHERE hu.status = 1 AND hu.mobile = ?\n" +
                                    "UNION\n" +
                                    "SELECT h.id AS houseId,1 AS TYPE,5 AS ownerType\n" +
                                    "FROM saas_house h WHERE h.org_id = ?";
                            list = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(HouseBindVO.class), args.toArray());
                        }
                    } else {
                        return ResultBean.failedResultWithMsg("验证码已失效");
                    }
                } else {
                    return ResultBean.failedResultWithMsg("验证码未找到或已过期");
                }
            }

            // 身份证号码查房屋
            if (StringUtils.isNotBlank(cardNumber)) {
                args.add(cardNumber);
                args.add(cardNumber);
                args.add(cardNumber);
                args.add(enterpriseId);
                String sql = "SELECT u.`house_id` AS houseId,1 AS TYPE,1 as ownerType\n" +
                        "FROM `saas_house_eligible_apply` a JOIN `saas_house_match_user` u ON a.id = u.`apply_id` WHERE u.`status` = 1 AND a.`card_number` = ?\n" +
                        "UNION\n" +
                        "SELECT u.`house_id` AS houseId,1 AS TYPE,2 as ownerType\n" +
                        "FROM `saas_house_eligible_apply_cohabit` c JOIN `saas_house_match_user` u ON c.apply_id = u.`apply_id` WHERE u.`status` = 1 and c.status in (1,4) AND c.`card_number` = ?\n" +
                        "UNION\n" +
                        "SELECT hu.community_house_id AS houseId,2 AS TYPE,(CASE hu.type WHEN 1 THEN 3 WHEN 2 THEN 4 END) AS ownerType\n" +
                        "FROM saas_community_house_user hu left join saas_app_user au on hu.mobile = au.phone WHERE hu.status = 1 AND au.card_number = ?\n" +
                        "UNION\n" +
                        "SELECT h.id AS houseId,1 AS TYPE,5 AS ownerType\n" +
                        "FROM saas_house h WHERE h.org_id = ?";
                list = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(HouseBindVO.class), args.toArray());
            }

            if (list.isEmpty()) {
                return ResultBean.failedResultWithMsg("房屋信息未找到，绑定失败");
            }

            houseBindRepository.deleteByUserId(userId);
            for (HouseBindVO vo : list) {
                HouseBind houseBind = new HouseBind();
                houseBind.setUserId(userId);
                houseBind.setType(vo.getType());
                houseBind.setOwnerType(vo.getOwnerType());
                houseBind.setHouseId(vo.getHouseId());
                houseBind.setStatus(1);
                houseBind.setCreateTime(date);
                houseBindRepository.save(houseBind);
            }

            return ResultBean.successfulResult(null);
        } catch (Exception e) {
            log.error("MyService houseBind Exception = {}" + e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }

    public ResultBean<CertificationVO> findCertification(String accessToken) {
        try {
            TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
            if (tokenRedisVo == null) {
                return ResultBean.failedResultOfToken();
            }
            String userId = tokenRedisVo.getId();

            AppUser user = appUserRepository.findByIdOrEnterpriseUserId(userId, userId);
            if (user == null) {
                return ResultBean.failedResultWithMsg("用户不存在");
            }

            CertificationVO vo = new CertificationVO();
            vo.setName(user.getName());
            vo.setPhone(user.getPhone());
            vo.setCardNumber(user.getCardNumber());
            vo.setFrontCardNumberPic(user.getFrontCardNumberPic());
            vo.setBackCardNumberPic(user.getBackCardNumberPic());
            vo.setFacePic(user.getFacePic());

            return ResultBean.successfulResult(vo);
        } catch (Exception e) {
            log.error("MyService findCertification Exception = {}" + e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }

    public ResultBean<ApiData<MyHouseVO>> findMyHouse(String accessToken, Integer pageNumber, Integer pageSize) {
        ResultBean<ApiData<MyHouseVO>> resultBean = new ResultBean<>();
        resultBean.setCode("10000");
        resultBean.setMsg("10000");
        ApiData<MyHouseVO> apiData = new ApiData<>();
        resultBean.setResultData(apiData);
        try {
            TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
            if (tokenRedisVo == null) {
                return ResultBean.failedResultOfToken();
            }
            String userId = tokenRedisVo.getId();

            List<Object> args = new ArrayList<>();
            args.add(userId);

            // 总记录数
            String countSql = "SELECT COUNT(1) AS tmpcount FROM `saas_house` h WHERE h.id IN (SELECT b.house_id FROM saas_house_bind b WHERE b.user_id = ? AND b.status = 1)";
            Long total = jdbcTemplate.queryForObject(countSql, args.toArray(), Long.class);
            if (total == 0) {
                return resultBean;
            }

            args.add(pageSize);
            args.add(pageNumber * pageSize);

            String sql = "SELECT h.id,h.residence_community_id AS residenceCommunityId,h.building_num AS buildingNum,h.unit,h.room_number AS roomNumber,h.area,h.`room`,h.`hall`,h.`toilet`,\n"
                    + "h.`province_id` AS provinceId,h.`city_id` AS cityId,h.`district_id` AS districtId,h.`street_id` AS streetId,h.`community_id` AS communityId,h.`address`\n"
                    + "FROM `saas_house` h WHERE h.id IN (SELECT b.house_id FROM saas_house_bind b WHERE b.user_id = ? and b.status = 1)" + ORDER + SQL_PAGE;
            List<MyHouseVO> houseList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(MyHouseVO.class), args.toArray());

            // 查询区域名称
            List<Long> ids = new ArrayList<>();
            List<Long> provinceIds = houseList.stream().filter(vo -> vo.getProvinceId() != null)
                    .map(MyHouseVO::getProvinceId).distinct().collect(Collectors.toList());
            List<Long> cityIds = houseList.stream().filter(vo -> vo.getCityId() != null).map(MyHouseVO::getCityId)
                    .distinct().collect(Collectors.toList());
            List<Long> districtIds = houseList.stream().filter(vo -> vo.getDistrictId() != null)
                    .map(MyHouseVO::getDistrictId).distinct().collect(Collectors.toList());
            List<Long> streetIds = houseList.stream().filter(vo -> vo.getStreetId() != null).map(MyHouseVO::getStreetId)
                    .distinct().collect(Collectors.toList());
            List<Long> communityIds = houseList.stream().filter(vo -> vo.getCommunityId() != null)
                    .map(MyHouseVO::getCommunityId).distinct().collect(Collectors.toList());
            ids.addAll(provinceIds);
            ids.addAll(cityIds);
            ids.addAll(districtIds);
            ids.addAll(streetIds);
            ids.addAll(communityIds);
            if (!ids.isEmpty()) {
                Map<Long, String> map = areaRepository.findByIdIn(ids).stream()
                        .collect(Collectors.toMap(Area::getId, Area::getName));
                if (!map.isEmpty()) {
                    for (MyHouseVO vo : houseList) {
                        vo.setProvince(map.get(vo.getProvinceId()));
                        vo.setCity(map.get(vo.getCityId()));
                        vo.setDistrict(map.get(vo.getDistrictId()));
                        vo.setStreet(map.get(vo.getStreetId()));
                        vo.setCommunity(map.get(vo.getCommunityId()));
                    }
                }
            }
            // 查询小区名称
            List<String> residenceCommunityIds = houseList.stream().filter(vo -> vo.getResidenceCommunityId() != null)
                    .map(MyHouseVO::getResidenceCommunityId).distinct().collect(Collectors.toList());
            if (!residenceCommunityIds.isEmpty()) {
                Map<String, String> map = communityRepository.findByIdIn(residenceCommunityIds).stream()
                        .collect(Collectors.toMap(Community::getId, Community::getName));
                if (!map.isEmpty()) {
                    houseList.forEach(vo -> vo.setResidenceCommunityName(map.get(vo.getResidenceCommunityId())));
                }
            }
            // 查询楼栋名称
            List<Long> buildingIds = houseList.stream().filter(vo -> vo.getBuildingNum() != null)
                    .map(MyHouseVO::getBuildingNum).distinct().collect(Collectors.toList());
            if (!buildingIds.isEmpty()) {
                Map<Long, String> map = communityBuildRepository.findByIdIn(buildingIds).stream()
                        .collect(Collectors.toMap(CommunityBuild::getId, CommunityBuild::getName));
                if (!map.isEmpty()) {
                    houseList.forEach(vo -> vo.setBuildingNumName(map.get(vo.getBuildingNum())));
                }
            }
            // 查询单元名称
            List<Long> unitIds = houseList.stream().filter(vo -> vo.getUnit() != null).map(MyHouseVO::getUnit)
                    .distinct().collect(Collectors.toList());
            if (!unitIds.isEmpty()) {
                Map<Long, String> map = communityBuildUnitRepository.findByIdIn(unitIds).stream()
                        .collect(Collectors.toMap(CommunityBuildUnit::getId, CommunityBuildUnit::getName));
                if (!map.isEmpty()) {
                    houseList.forEach(vo -> vo.setUnitName(map.get(vo.getUnit())));
                }
            }

            apiData.setData(houseList);
            apiData.setTotal(total);

            resultBean.setResultData(apiData);
        } catch (Exception e) {
            log.error("MyService findMyHouse Exception = {}" + e.getMessage(), e);
            resultBean.setCode("10001");
            resultBean.setMsg("10001");
        }
        resultBean.setResultData(apiData);
        return resultBean;
    }

    /**
     * 提现
     *
     * @param accessToken
     * @param vo
     * @return
     * @author shun
     * @date 2021年6月21日
     */
    @Transactional(rollbackFor = {RuntimeException.class, Exception.class})
    public ResultBean<Object> accountWithdrawal(String accessToken, AccountWithdrawalVO vo) {
        log.info(" 钱包提现, vo={}", JSON.toJSONString(vo));

        if (vo.getStoreType() == null || vo.getType() == null || vo.getAmount() == null || vo.getName() == null) {
            return ResultBean.failedResultWithMsg("参数有误");
        }

        if (vo.getType() == PaymentTypeEnum.ALI.getValue() && vo.getAccount() == null) {
            return ResultBean.failedResultWithMsg("账户不能为空");
        }

        if (vo.getType() == PaymentTypeEnum.WECHAT.getValue() && vo.getOpenid() == null) {
            return ResultBean.failedResultWithMsg("openid不能为空");
        }

        // 操作用户缓存信息
        TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
        if (tokenRedisVo == null) {
            return ResultBean.failedResultOfToken();
        }
        // 保存提现记录
        String userId = tokenRedisVo.getId();
        // 操作用户企业id
        Long enterpriseId = vo.getOrgId();
        if (vo.getOrgId() == null) {
            enterpriseId = tokenRedisVo.getEnterpriseId();
        }

        // 验证当前用户是否为当前企业提现人
        List<WithdrawUser> withdrawUsers = withdrawUserRepository.findByOrgIdAndStatus(enterpriseId, 1);
        if (withdrawUsers.isEmpty()) {
            return ResultBean.failedResultWithMsg("企业未设置提现人，无法操作");
        } else if (!withdrawUsers.isEmpty()) {
            boolean flag = true;
            for (WithdrawUser withdrawUser : withdrawUsers) {
                if (withdrawUser.getUserId().equals(userId)) {
                    flag = false;
                    break;
                }
            }

            if (flag) {
                return ResultBean.failedResultWithMsg("当前用户不是企业提现人，无法操作");
            }
        }

        Wallet wallet = walletRepository.findByOrgIdAndStoreTypeAndType(enterpriseId, vo.getStoreType(), vo.getType());
        if (wallet == null) {
            log.warn(" 钱包提现, 提现企业无相关钱包信息, orgid={}, storeType={}, type={}", enterpriseId, vo.getStoreType(),
                    vo.getType());
            return ResultBean.failedResultWithMsg("钱包信息有误");
        }

        if (wallet.getUsableAmount() < vo.getAmount()) {
            log.warn(" 钱包提现, 钱包余额不足, usableAmount={}, amount={}", wallet.getUsableAmount(), vo.getAmount());
            return ResultBean.failedResultWithMsg("钱包余额不足");
        }

        // 查询商户号信息
        WechatAccount wechatAccount = wechatAccountRepository.findByOrgIdAndType(enterpriseId, vo.getType());
        if (wechatAccount == null) {
            log.warn(" 钱包提现, 商户信息未找到, orgid={}, type={}", enterpriseId, vo.getType());
            return ResultBean.failedResultWithMsg("商户信息未找到");
        }

        WithdrawRecord entity = new WithdrawRecord();
        entity.setOrgId(enterpriseId);
        entity.setOperatorId(userId);
        entity.setPayeeName(vo.getName());
        entity.setPayeeAccount(vo.getAccount());
        entity.setType(vo.getType());
        entity.setTransAmount(vo.getAmount());
        entity.setWalletId(wallet.getId());
        entity.setServiceAmount(0);
        entity.setTransferFee(0);
        entity.setWithdrawAmount(vo.getAmount());
        entity.setStatus(0);
        entity.setWithdrawTime(new Date());
        withdrawRecordRepository.save(entity);

        String reString = null;
        // 执行转账操作
        if (vo.getType() == PaymentTypeEnum.ALI.getValue()) {
            // 支付宝转账
            reString = aliWithraw(entity, wechatAccount);
        } else {
            if (wechatAccount.getMchCertificate() == null || wechatAccount.getMchCertificate().length <= 0) {
                log.info(" 钱包提现, 未上传证书! orgId={}", entity.getOrgId());
                return ResultBean.failedResultWithMsg("商户信息有误");
            }
            // 微信提现到零钱
            reString = wxWithraw(entity, wechatAccount, vo.getOpenid());
        }
        withdrawRecordRepository.save(entity);

        // 提现成功
        if ("success".equals(reString)) {
            // 钱包金额调整
            // 累计提现金额 = 累计提现金额 + 提现金额
            wallet.setTotalWithdrawAmount(wallet.getTotalWithdrawAmount() + vo.getAmount());
            // 钱包可提现金额 = 钱包可提现金额 - 提现金额
            wallet.setUsableAmount(wallet.getUsableAmount() - vo.getAmount());
            // 钱包总余额 = 钱包总余额 - 提现金额
            wallet.setBalanceAmount(wallet.getBalanceAmount() - vo.getAmount());
            wallet.setLastUpdateTime(new Date());
            walletRepository.save(wallet);
        } else {
            return ResultBean.failedResultWithMsg(reString);
        }

        return ResultBean.successfulResult(null);
    }

    /**
     * 支付宝单笔转账
     *
     * @param entity
     * @param account
     * @author shun
     * @date 2021年6月21日
     */
    public String aliWithraw(WithdrawRecord entity, WechatAccount account) {
        // 雪花算法自动生成
        String outTradeNo = String.valueOf(KeyWorker.nextId());

        BigDecimal transAmount = ConvertUtils.fen2yuan(entity.getTransAmount());
        AliWithdraw aliWithdraw = new AliWithdraw(account.getMchId(), account.getPrivateKey(), account.getPublicKey(),
                outTradeNo, transAmount, "TRANS_ACCOUNT_NO_PWD", null, entity.getPayeeAccount(), "ALIPAY_LOGON_ID",
                entity.getPayeeName());

        AlipayFundTransToaccountTransferResponse response = new AliTransfers(aliWithdraw).toTransfers();
        if (response != null && response.isSuccess()) {
            // 转账成功
            log.info(" 钱包提现, 提现转账成功! orgId={}", entity.getWalletId());
            // 保存转账记录
            WithdrawTransferRecord transferRecord = new WithdrawTransferRecord();
            transferRecord.setWithdrawId(entity.getId());
            transferRecord.setPayeeName(entity.getPayeeName());
            transferRecord.setPayeeAccount(entity.getPayeeAccount());
            transferRecord.setTransAmount(entity.getTransAmount());
            transferRecord.setCode(response == null ? null : response.getCode());
            transferRecord.setMsg(response == null ? null : response.getMsg());
            transferRecord.setSubCode(response == null ? null : response.getSubCode());
            transferRecord.setSubMsg(response == null ? null : response.getSubMsg());
            transferRecord.setOutBizNo(outTradeNo);
            transferRecord.setPayDate(
                    response == null ? null : DateUtils.convert(response.getPayDate(), DateUtils.FORMAT_DATETIME_14));
            transferRecord.setOrderId(response.getOrderId());

            withdrawTransferRecordRepository.save(transferRecord);
            entity.setStatus(1);

            return "success";
        } else {
            entity.setStatus(2);
            entity.setRemark(response.getSubMsg());
            return response.getSubMsg();
        }
    }

    /**
     * 微信-企业付款到零钱
     *
     * @param entity
     * @param account
     * @param openid
     * @author shun
     * @date 2021年6月21日
     */
    public String wxWithraw(WithdrawRecord entity, WechatAccount account, String openid) {
        // 雪花算法自动生成
        String outTradeNo = String.valueOf(KeyWorker.nextId());
        String appId = redisService.getValue(Constant.WX_APPID);

        WxWithdraw wxWithdraw = new WxWithdraw(appId, account.getMchApiKey(), account.getMchId(), outTradeNo, openid,
                entity.getPayeeName(), entity.getTransAmount(), "提现", account.getMchCertificate(),
                payConfig.getWxTransfersUrl());

        WxWithdrawRes vRes = new WxTransfersRequest(wxWithdraw).toTransfers();
        if (vRes != null && "SUCCESS".equals(vRes.getResultCode())) {
            // 转账成功
            log.info(" 钱包提现, 提现转账成功! orgId={}", entity.getOrgId());
            // 保存转账记录
            WithdrawTransferRecord transferRecord = new WithdrawTransferRecord();
            transferRecord.setWithdrawId(entity.getId());
            transferRecord.setPayeeName(entity.getPayeeName());
            transferRecord.setPayeeAccount(entity.getPayeeAccount());
            transferRecord.setTransAmount(entity.getTransAmount());
            transferRecord.setCode(vRes.getReturnCode());
            transferRecord.setMsg(vRes.getReturnMsg());
            transferRecord.setSubCode(vRes.getResultCode());
            // transferRecord.setSubMsg();
            transferRecord.setOutBizNo(outTradeNo);
            transferRecord.setPayDate(DateUtils.convert(vRes.getPaymentTime(), DateUtils.FORMAT_DATETIME_14));
            transferRecord.setOrderId(vRes.getPartnerTradeNo());

            withdrawTransferRecordRepository.save(transferRecord);
            entity.setStatus(1);

            return "success";
        } else {
            log.info(" 钱包提现, 提现转账失败! return_code={}, return_msg={}", vRes.getResultCode(), vRes.getReturnMsg());
            entity.setStatus(2);
            entity.setRemark(vRes.getReturnMsg());
            return vRes.getReturnMsg();
        }
    }

    /**
     * 钱包明细
     *
     * @param accessToken
     * @param pageNumber
     * @param pageSize
     * @return
     * @author shun
     * @date 2021年6月23日
     */
    public ResultBean<WalletDetailVO> withdrawList(String accessToken, Integer pageNumber, Integer pageSize) {
        ResultBean<WalletDetailVO> resultBean = new ResultBean<>();
        resultBean.setCode("10000");
        resultBean.setMsg("10000");
        WalletDetailVO apiData = new WalletDetailVO();
        resultBean.setResultData(apiData);
        try {
            TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
            if (tokenRedisVo == null) {
                return ResultBean.failedResultOfToken();
            }
            String userId = tokenRedisVo.getId();
            Long enterpriseId = tokenRedisVo.getEnterpriseId();

            //提现人标识
            List<WithdrawUser> withdrawUsers = withdrawUserRepository.findByOrgIdAndStatusAndUserId(enterpriseId, 1, userId);
            if (!withdrawUsers.isEmpty()) {
                apiData.setFlag(1);
            } else {
                apiData.setFlag(0);
            }

            // 查询汇总信息
            String sql = "select w.store_type as storeType, w.type, w.balance_amount as balanceAmount,"
                    + "w.usable_amount as usableAmount,w.buffer_amount as bufferAmount,w.total_amount as totalAmount, w.total_withdraw_amount as totalWithdrawAmount  "
                    + "from saas_wallet w where w.org_id = ?";
            List<WalletVO> walletlist = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(WalletVO.class),
                    new Object[]{tokenRedisVo.getEnterpriseId()});
            apiData.setWalletList(walletlist);

            // 总记录数
            Long total = jdbcTemplate.queryForObject("select count(1) from saas_withdraw_record r where r.org_id = ?",
                    new Object[]{tokenRedisVo.getEnterpriseId()}, Long.class);
            if (total != 0) {
                List<WithdrawRecord> list = jdbcTemplate.query(
                        "SELECT r.* FROM saas_withdraw_record r WHERE r.org_id = ? order by withdraw_time desc LIMIT ? OFFSET ?",
                        new BeanPropertyRowMapper<>(WithdrawRecord.class),
                        new Object[]{tokenRedisVo.getEnterpriseId(), pageSize, pageNumber * pageSize});

                List<WithdrawRecordVO> withdrawRecordList = new ArrayList<>();
                for (WithdrawRecord entity : list) {
                    WithdrawRecordVO vo = new WithdrawRecordVO();
                    BeanUtils.copyProperties(entity, vo);

                    vo.setWithdrawTime(DateUtils.format(entity.getWithdrawTime(), DateUtils.FORMAT_DATETIME_14));
                    withdrawRecordList.add(vo);
                }

                apiData.setTotal(total);
                apiData.setWithdrawList(withdrawRecordList);
            }
            resultBean.setResultData(apiData);
        } catch (Exception e) {
            log.error("LockBrandService lockBrandList Exception = {}" + e.getMessage(), e);
            resultBean.setCode("10001");
            resultBean.setMsg("10001");
        }
        resultBean.setResultData(apiData);
        return resultBean;
    }

    /**
     * 切换账户
     *
     * @param accessToken
     * @param type
     * @return
     * @author shun
     * @date 2021年6月24日
     */
    public ResultBean<Object> accountSwitch(String accessToken, Integer type) {
        log.info(" accountSwitch, accessToken={}, type={}", accessToken, type);
        ResultBean<Object> result = new ResultBean<>();
        TokenRedisVo tokenRedisVo = redisService.swichUserTokenVo(accessToken);
        try {
            if (tokenRedisVo == null || type == null) {
                result.setCode(StatusCode.ERROR_CODE_40001.getErrorCode());
                result.setMsg(StatusCode.ERROR_CODE_40001.getErrorMsg());
                return result;
            }

            if (type == UserLoginTypeEnum.ENTERPRISE.getValue()) {
                AppUser appUser = appUserRepository.findByIdOrEnterpriseUserId(tokenRedisVo.getId(), tokenRedisVo.getId());
                if (appUser == null) {
                    result.setCode(StatusCode.ERROR_CODE_40001.getErrorCode());
                    result.setMsg("用户信息错误");
                    return result;
                }
                tokenRedisVo.setLoginType(UserLoginTypeEnum.ENTERPRISE.getValue());
                tokenRedisVo.setEnterpriseUserId(appUser.getEnterpriseUserId());

                List<UserDepartmentRef> userDepartmentRefList = userDepartmentRefRepository.findByUserId(appUser.getEnterpriseUserId());
                Long depId = null;
                if (userDepartmentRefList != null && userDepartmentRefList.size() != 0) {
                    depId = userDepartmentRefList.get(0).getDepId();
                }
                Long enterpriseId = userService.findCompanyByUserDepId(depId);
                if (enterpriseId == null) {
                    return ResultBean.failedResultWithMsg("账号信息有误，企业信息不存在");
                }
                tokenRedisVo.setEnterpriseId(enterpriseId);
            } else {
                tokenRedisVo.setLoginType(UserLoginTypeEnum.CONSUMER.getValue());
                tokenRedisVo.setEnterpriseUserId(null);
                tokenRedisVo.setEnterpriseId(null);
            }

            // 更新缓存
            tokenService.updateAuthTokenInfo(accessToken, tokenRedisVo);
            Map<String, Object> resultMap = new HashMap<String, Object>();
            resultMap.put("accessToken", accessToken);
            result.setResultData(resultMap);

            result.setMsg(StatusCode.SUCCESS_CODE_10000.getErrorMsg());
            result.setCode(StatusCode.SUCCESS_CODE_10000.getErrorCode());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            result.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
            result.setMsg(e.getMessage());
        }

        return result;
    }

    /*public ResultBean<Object> validatePhone(String accessToken, String phone, String code) {
        try {
            TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
            if (tokenRedisVo == null) {
                return ResultBean.failedResultOfToken();
            }

            if (StringUtils.isNotBlank(phone) && StringUtils.isNotBlank(code)) {
                // 验证验证码
                String redisPhone = redisService.getSmsCodeMobile(code);
                if (StringUtils.isNotBlank(redisPhone)) {
                    if (redisPhone.equals(phone)) {
                        return ResultBean.successfulResult(null);
                    } else {
                        return ResultBean.failedResultWithMsg("手机号码匹配失败");
                    }
                } else {
                    return ResultBean.failedResultWithMsg("验证码未找到或已过期");
                }
            }
            return ResultBean.failedResultWithMsg("参数有误");
        } catch (Exception e) {
            log.error("MyService houseBind Exception = {}" + e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }*/

    /**
     * 原手机号码验证
     *
     * @param accessToken
     * @param phone
     * @param password
     * @return
     */
    public ResultBean<Object> validatePhone(String accessToken, String phone, String password) {
        try {
            TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
            if (tokenRedisVo == null) {
                return ResultBean.failedResultOfToken();
            }

            if (StringUtils.isNotBlank(phone) && StringUtils.isNotBlank(password)) {
                AppUser user = appUserRepository.findByPhone(phone);

                // 验证密码
                byte[] inputHashPwd = Digests.sha1(password.getBytes(), Encodes.decodeHex(user.getSalt()),
                        HASH_INTERATIONS);
                String inputPwd = Encodes.encodeHex(inputHashPwd);

                if (!StringUtils.equals(inputPwd, user.getPassword())) {
                    return ResultBean.failedResultWithMsg("密码错误");
                }

                return ResultBean.successfulResult(null);
            }

            return ResultBean.failedResultWithMsg("参数有误");
        } catch (Exception e) {
            log.error("MyService validatePhone Exception = {}" + e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }

    /**
     * 用户更换手机号码
     *
     * @param accessToken
     * @param phone
     * @param code
     * @return
     * @author shun
     * @date 2021年6月28日
     */
    public ResultBean<Object> updatePhone(String accessToken, String phone, String code) {
        try {
            TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
            if (tokenRedisVo == null) {
                return ResultBean.failedResultOfToken();
            }
            String userId = tokenRedisVo.getId();
            String mobile = tokenRedisVo.getPhone();
            if (StringUtils.isNotBlank(phone) && StringUtils.isNotBlank(code)) {
                // 验证验证码
                String redisPhone = redisService.getSmsCodeMobile(code);
                if (StringUtils.isNotBlank(redisPhone)) {
                    if (redisPhone.equals(phone)) {
                        // 查询登录用户信息
                        AppUser loginUser = appUserRepository.findByIdOrEnterpriseUserId(userId, userId);
                        if (loginUser == null) {
                            log.info("更换手机号码, 登录用户信息未找到, userId={}, phone={}", userId, phone);
                            return ResultBean.failedResultWithMsg("用户信息有误");
                        }
                        // 查询更改后手机号码是否有注册
                        AppUser appUser = appUserRepository.findByPhone(phone);
                        if (appUser != null) {
                            log.info("更换手机号码, 手机号码已存在, phone={}", phone);
                            return ResultBean.failedResultWithMsg("手机号码已存在");
                        }

                        // 同步更改企业端用户手机号码 20220328
                        if(loginUser.getEnterpriseUserId() != null){
                        	User user = userRepository.findUserById(loginUser.getEnterpriseUserId());
                        	if(user != null){
                        		user.setMobile(phone);
                        		userRepository.save(user);
                        	}
                        }

                        // 同步成员手机号码20220328
                        // 租客
                        if(loginUser.getPhone() != null){
                        	List<CommunityHouseUser> communityHouseUsers = communityHouseUserRepository.findByMobileAndStatus(loginUser.getPhone(), 1);
                            if(!communityHouseUsers.isEmpty()){
                            	communityHouseUsers.forEach(c ->{
                            		c.setMobile(phone);
                            	});
                            	communityHouseUserRepository.saveAll(communityHouseUsers);
                            }
                        }
                        //同步用户智能锁授权信息20230223
                        List<SmartLockAuth> byMobileList = smartLockAuthRepository.findByMobile(mobile);
                        if (!byMobileList.isEmpty()) {
                            for (SmartLockAuth smartLockAuth : byMobileList) {
                                smartLockAuth.setMobile(phone);
                                smartLockAuthRepository.save(smartLockAuth);
                            }
                        }
                        loginUser.setPhone(phone);
                        appUserRepository.save(loginUser);
                        return ResultBean.successfulResult(null);
                    } else {
                        return ResultBean.failedResultWithMsg("手机号码匹配失败");
                    }
                } else {
                    return ResultBean.failedResultWithMsg("验证码未找到或已过期");
                }
            }
            return ResultBean.failedResultWithMsg("参数有误");
        } catch (Exception e) {
            log.error("MyService houseBind Exception = {}" + e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }

    @Transactional
    public ResultBean<Object> houseUnbind(String accessToken, HouseUnbindVO vo) {
        try {
            TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
            if (tokenRedisVo == null) {
                return ResultBean.failedResultOfToken();
            }
            String userId = tokenRedisVo.getId();

            if (StringUtils.isBlank(vo.getId())) {
                return ResultBean.failedResultOfParamWithMsg("房屋id不存在");
            }
            if (StringUtils.isBlank(vo.getPhone())) {
                return ResultBean.failedResultOfParamWithMsg("手机号不存在");
            }
            if (StringUtils.isBlank(vo.getCode())) {
                return ResultBean.failedResultOfParamWithMsg("验证码不存在");
            }

            // 验证验证码
            String redisPhone = redisService.getSmsCodeMobile(vo.getCode());
            if (!StringUtils.isBlank(redisPhone)) {
                if (redisPhone.equals(vo.getPhone())) {
                    houseBindRepository.deleteByHouseIdAndUserId(vo.getId(), userId);
                } else {
                    return ResultBean.failedResultWithMsg("验证码已失效");
                }
            } else {
                return ResultBean.failedResultWithMsg("验证码未找到或已过期");
            }

            return ResultBean.successfulResult(null);
        } catch (Exception e) {
            log.error("MyService houseUnbind Exception = {}" + e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }

    /**
     * 注销
     * @param accessToken
     * @return
     * @author shun
     * @date 2022年2月22日
     */
    public ResultBean<Object> logout(String accessToken) {
        log.info("MyService logout accessToken={}", accessToken);
        TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
        if (tokenRedisVo == null) {
            return ResultBean.failedResultOfToken();
        }
        String userId = tokenRedisVo.getId();
        // 查询登录用户信息
        AppUser user = appUserRepository.findByIdOrEnterpriseUserId(userId, userId);

        if (user == null) {
            return ResultBean.failedResultOfParamWithMsg("用户不存在");
        }
        // 注销
        user.setStatus(4);
        appUserRepository.save(user);

        // 删除登录token缓存
        redisService.deleteLoginToken(accessToken);
        return ResultBean.successfulResult(null);
    }
}
